//+----------------------+ //|InAt20 from Shell_20c | //+----------------------+ #property copyright "Ron Thompson" #property link "http://www.ForexMT4.com/" // This EA is NEVER to be SOLD individually // This EA is NEVER to be INCLUDED as part of a collection that is SOLD // user input extern string Pairs = "AUDCAD,AUDCHF,AUDJPY,AUDNZD,AUDUSD,CADCHF,CHFJPY,EURAUD,EURCAD,EURCHF,EURGBP,EURJPY,EURNZD,EURTRY,EURUSD,GBPAUD,GBPCAD,GBPCHF,GBPJPY,GBPNZD,GBPTRY,GBPUSD,NZDCAD,NZDCHF,NZDJPY,NZDUSD,TRYJPY,USDCAD,USDCHF,USDJPY,USDTRY" ; extern double Lots = 0.1 ; extern double ProfitMade = 100 ; extern double LossLimit = 20 ; extern double BasketProfit = 0 ; extern double BasketTrail = 0 ; extern double BasketLoss = 0 ; extern double BreakEven = 0 ; extern double TrailStop = 0 ; extern int LogLevel = 1 ; extern bool KillLogging = true ; static bool TradeEnabled=false; // MULTI Pair handling // hard coded to use current symbol() for testing string Pairz[100]; static bool TradeAllowed[100]; static datetime bartime[100]; int ptrPMAX; int ptrPairz=0; string mySymbol; double bid; double ask; // Trade control double myPoint; // support for 3/5 decimal places int Slippage=2; // how many pips of slippage can you tolorate int loopcount; // count of order attempts int maxloop=3; // maximum number of attempts to handle errors int LL2SL=50; // LossLimit to StopLoss server spread int MagicNumber = 143637101; // allows multiple experts to trade on same account string TradeComment = "_InAt20_1a.txt"; // where to log information // Statistics int maxOrders; // statistic for maximum numbers or orders open at one time //baskettrail double btrail=0; // trail the basket (Symbol() and MagicNumber) // used for verbose error logging #include //+-------------+ //| Custom init | //|-------------+ // Called ONCE when EA is added to chart or recompiled int init() { // ptrPMAX is used as a counter in INIT so that when // INIT is complere, ptrPMAX will be equal to the // last element count +1 // That way 'if's can say >ptrPMAX instead of >= int i,j; int cnt; string cmt; // Split the user string into an array int pcomma=0; int comma=0; //clear the arrays for (i=0; i<100; i++) { // in case there were previous data Pairz[i]=""; // so it will tick once bartime[i]=iTime(mySymbol, 0, 0); // disable usual trades TradeAllowed[i]=false; } // if backtesting then set array to current symbol only if( IsTesting() ) { Pairz[0]=Symbol(); ptrPMAX=1; logwrite(TradeComment,"---ISTESTING--- Array set to single element of this pair"); Print("---ISTESTING--- Array set to single element of this pair"); } // if nothing in the extern that we can use (empty or garbage) // then set array to current symbol only if(StringLen(Pairs)<6) { Pairz[0]=Symbol(); ptrPMAX=1; logwrite(TradeComment,"---EMPTY/CORRUPTED--- Array set to single element of this pair"); } //Load all of the symbols while ( StringLen(Pairs)>=6 && !IsTesting() ) { //save the old comma pcomma=comma; // find the next comma comma=StringFind(Pairs, ",", pcomma+1); // Gather trailing(or only) pair // (no comma following last/only pair) // then leave (accounts for one pair on line) if(comma<0) { Pairz[ptrPMAX]=StringSubstr(Pairs, pcomma+1, comma-pcomma); logwrite(TradeComment,ptrPMAX+" "+Pairz[ptrPMAX]+" --- LAST ELEMENT ---"); break; } // store the pair into an array if(ptrPMAX==0) Pairz[ptrPMAX]=StringSubstr(Pairs, pcomma, comma-pcomma); if(ptrPMAX >0) Pairz[ptrPMAX]=StringSubstr(Pairs, pcomma+1, comma-pcomma-1); logwrite(TradeComment,ptrPMAX+" "+Pairz[ptrPMAX]); // increment pointer for next elemant ptrPMAX++; if(ptrPMAX>100) break; }//while Comment(""); logwrite(TradeComment,"Init Complete"); }//init //+----------------+ //| Custom DE-init | //+----------------+ // Called ONCE when EA is removed from chart int deinit() { // always indicate deinit statistics logwrite(TradeComment,"MAX number of orders "+maxOrders); Comment(" "); logwrite(TradeComment,"DE-Init Complete"); } //+-----------+ //| Main | //+-----------+ // Called EACH TICK and each Bar[] int start() { // The following MUST be done before anything else // step through each pair, once a tick ptrPairz++; if(ptrPairz>=ptrPMAX) ptrPairz=0; mySymbol=Pairz[ptrPairz]; Comment("Now trading -"+mySymbol+"- at position "+ptrPairz ); // get normalized Point based on Broker decimal places // every tick, since we may be using multi-pairs myPoint = SetPoint(); // end 'MUST' int i; int cnt=0; int gle=0; int ticket=0; int OrdersPerSymbol=0; int OpenOrders=0; // stoploss and takeprofit and close control double SL=0; double TP=0; double CurrentProfit=0; double CurrentBasket=0; // direction control bool BUYme=false; bool SELLme=false; double MaCurrent; double MaPrevious; //safety counter int loopcount=0; OrdersPerSymbol=0; for(cnt=OrdersTotal();cnt>=0;cnt--) { OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES); if( OrderSymbol()==mySymbol && OrderMagicNumber()==MagicNumber) OrdersPerSymbol++; } // keep some statistics if(OrdersPerSymbol>maxOrders) maxOrders=OrdersPerSymbol; OpenOrders=0; for(cnt=OrdersTotal();cnt>=0;cnt--) { OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES); if( OrderMagicNumber()==MagicNumber) OpenOrders++; } if(OpenOrders==0) TradeEnabled=true; // bar counting if(bartime[ptrPairz]!=iTime(mySymbol, 0, 0) ) { bartime[ptrPairz]=iTime(mySymbol, 0, 0) ; } //+-----------------------------+ //| Insert your indicator here | //| And set either BUYme or | //| SELLme true to place orders | //| | //+-----------------------------+ // This code runs once, until expert restarted if(TradeEnabled) { for(i=0; i=0;cnt--) { OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES); if( OrderSymbol()==mySymbol && OrderMagicNumber()==MagicNumber) { // add up pips //if(OrderType()==OP_BUY ) CurrentBasket=CurrentBasket+( Close[0]-OrderOpenPrice() ); //if(OrderType()==OP_SELL ) CurrentBasket=CurrentBasket+( (Close[0]-OrderOpenPrice()) * (-1) ); //add up dollars if(OrderType()==OP_BUY ) CurrentBasket=CurrentBasket+( OrderProfit() ); if(OrderType()==OP_SELL ) CurrentBasket=CurrentBasket+( OrderProfit() ); } } if( BasketProfit>0 && CurrentBasket>=BasketProfit ) { CloseEverything(); btrail=0; } if( BasketLoss >0 && CurrentBasket<=BasketLoss*(-1) ) { CloseEverything(); btrail=0; } //basket trailing stop //calculate trail if(BasketTrail>0 && CurrentBasket>BasketTrail) { if(CurrentBasket>btrail) { btrail=CurrentBasket; } } //close on retrace if(btrail>0 && CurrentBasket<(btrail-BasketTrail)) { CloseEverything(); btrail=0; } for(cnt=OrdersTotal();cnt>=0;cnt--) { OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES); if( OrderSymbol()==mySymbol && OrderMagicNumber()==MagicNumber ) { if(OrderType()==OP_BUY) { bid=MarketInfo(mySymbol,MODE_BID); CurrentProfit=(bid-OrderOpenPrice()) ; // // Modify for break even //======================= // // OrderStopLoss will be equal to OrderOpenPrice if this event happens // thus it will only ever get executed one time per ticket if( BreakEven>0 ) { if (CurrentProfit >= BreakEven*myPoint && OrderOpenPrice()>OrderStopLoss()) { bid=MarketInfo(mySymbol,MODE_BID); ask=MarketInfo(mySymbol,MODE_ASK); SL=OrderOpenPrice()+(ask-bid); TP=OrderTakeProfit(); OrderModify(OrderTicket(),OrderOpenPrice(),SL,TP, White); gle=GetLastError(); if(gle==0) { logwrite(TradeComment,"MODIFY BUY BE Ticket="+OrderTicket()+" SL="+SL+" TP="+TP); } else { logwrite(TradeComment,"-----ERROR----- MODIFY BUY BE Bid="+Bid+" error="+gle+" "+ErrorDescription(gle)); } } } // // check for trailing stop //========================= // // This starts trailing after 'TrailStop' pips of profit if( TrailStop>0 && iClose(mySymbol,0,0)>OrderOpenPrice()+(TrailStop*myPoint) ) { bid=MarketInfo(mySymbol,MODE_BID); if( OrderStopLoss() < bid-(TrailStop*myPoint) ) { SL=bid-(TrailStop*myPoint); TP=OrderTakeProfit(); OrderModify(OrderTicket(),OrderOpenPrice(),SL,TP,0,White); gle=GetLastError(); if(gle==0) { logwrite(TradeComment,"MODIFY BUY TS Ticket="+OrderTicket()+" SL="+SL+" TP="+TP); } else { logwrite(TradeComment,"-----ERROR----- MODIFY BUY TS Bid="+bid+" error="+gle+" "+ErrorDescription(gle)+" "); } } } // Did we make a profit //====================== if(ProfitMade>0 && CurrentProfit>=(ProfitMade*myPoint)) { CloseBuy("PROFIT"); } // Did we take a loss //==================== if(LossLimit>0 && CurrentProfit<=(LossLimit*(-1)*myPoint)) { CloseBuy("LOSS"); } } // if BUY if(OrderType()==OP_SELL) { ask=MarketInfo(mySymbol,MODE_ASK); CurrentProfit=(OrderOpenPrice()-ask); //logwrite(TradeComment,"SELL CurrentProfit="+CurrentProfit/myPoint+" CurrentBasket="+CurrentBasket/myPoint); // // Modify for break even //======================= // // OrderStopLoss will be equal to OrderOpenPrice if this event happens // thus it will only ever get executed one time per ticket if( BreakEven>0 ) { if (CurrentProfit >= BreakEven*myPoint && OrderOpenPrice()0 && iClose(mySymbol,0,0) ask+(TrailStop*myPoint) ) { SL=ask+(TrailStop*myPoint); TP=OrderTakeProfit(); OrderModify(OrderTicket(),OrderOpenPrice(),SL,TP,0,Red); gle=GetLastError(); if(gle==0) { logwrite(TradeComment,"MODIFY SELL TS Ticket="+OrderTicket()+" SL="+SL+" TP="+TP); } else { logwrite(TradeComment,"-----ERROR----- MODIFY SELL TS Ask="+Ask+" error="+gle+" "+ErrorDescription(gle)); } } } // Did we make a profit //====================== if( ProfitMade>0 && CurrentProfit>=(ProfitMade*myPoint) ) { CloseSell("PROFIT"); } // Did we take a loss //==================== if( LossLimit>0 && CurrentProfit<=(LossLimit*(-1)*myPoint) ) { CloseSell("LOSS"); } } //if SELL } // if(OrderSymbol) } // for } // start() //+-----------------+ //| CloseEverything | //+-----------------+ // Closes all OPEN and PENDING orders int CloseEverything() { int i; for(i=OrdersTotal();i>=0;i--) { OrderSelect(i, SELECT_BY_POS); if(OrderSymbol()==mySymbol && OrderMagicNumber()==MagicNumber) { if(OrderType()==OP_BUY) CloseBuy ("BASKET"); if(OrderType()==OP_SELL) CloseSell("BASKET"); if(OrderType()==OP_BUYLIMIT) OrderDelete( OrderTicket() ); if(OrderType()==OP_SELLLIMIT) OrderDelete( OrderTicket() ); if(OrderType()==OP_BUYSTOP) OrderDelete( OrderTicket() ); if(OrderType()==OP_SELLSTOP) OrderDelete( OrderTicket() ); } Sleep(1000); } //for } // closeeverything // log data to a file name passed in // print everything regardless of log setting void logwrite (string filename, string mydata) { int myhandle; string gregorian=TimeToStr(CurTime(),TIME_DATE|TIME_SECONDS); Print(" "+mySymbol+" "+mydata+" "+gregorian); // don't log anything if testing or if user doesn't want it if(IsTesting()) return(0); if(KillLogging) return(0); myhandle=FileOpen(mySymbol+"_"+filename, FILE_CSV|FILE_WRITE|FILE_READ, ";"); if(myhandle>0) { FileSeek(myhandle,0,SEEK_END); FileWrite(myhandle, " "+mySymbol+" "+mydata+" "+gregorian); FileClose(myhandle); } } //ENTRY LONG (buy, Ask) void OpenBuy() { int gle=0; int ticket=0; double SL=0; double TP=0; int loopcount; // PLACE order is independent of MODIFY order. // This is mandatory for ECNs and acceptable for retail brokers loopcount=0; while(true) { bid=MarketInfo(mySymbol,MODE_BID); ask=MarketInfo(mySymbol,MODE_ASK); // place order - NO TP OR SL ticket=OrderSend(mySymbol,OP_BUY,Lots,ask,Slippage,0,0,TradeComment,MagicNumber,White); gle=GetLastError(); if(gle==0) { logwrite(TradeComment,"BUY PLACED Ticket="+ticket+" Ask="+ask+" Lots="+Lots); TradeAllowed[ptrPairz]=false; break; } else { logwrite(TradeComment,"-----ERROR----- Placing BUY order: Lots="+Lots+" Bid="+bid+" Ask="+ask+" ticket="+ticket+" Err="+gle+" "+ErrorDescription(gle)); RefreshRates(); Sleep(500); // give up after loopcount tries loopcount++; if(loopcount>maxloop) { logwrite(TradeComment,"-----ERROR----- Giving up on placing BUY order"); return(gle); } } }//while - place order // modify the order for users TP & SL loopcount=0; while(true) { bid=MarketInfo(mySymbol,MODE_BID); ask=MarketInfo(mySymbol,MODE_ASK); // don't set TP and SL both to zero, they're already there if(LossLimit==0 && ProfitMade==0) break; if(LossLimit ==0) SL=0; if(ProfitMade ==0) TP=0; if(LossLimit >0) SL=ask-((LossLimit+LL2SL)*myPoint ); if(ProfitMade >0) TP=ask+((ProfitMade+LL2SL)*myPoint ); OrderModify(ticket,OrderOpenPrice(),SL,TP,0,White); gle=GetLastError(); if(gle==0) { logwrite(TradeComment,"BUY OPENMOD Ticket="+ticket+" Ask="+ask+" Lots="+Lots+" SL="+SL+" TP="+TP); break; } else { logwrite(TradeComment,"-----ERROR----- Modifying BUY order: Lots="+Lots+" SL="+SL+" TP="+TP+" Bid="+bid+" Ask="+ask+" ticket="+ticket+" Err="+gle+" "+ErrorDescription(gle)); RefreshRates(); Sleep(500); loopcount++; if(loopcount>maxloop) { logwrite(TradeComment,"-----ERROR----- Giving up on modifying BUY order"); return(gle); } } }//while - modify order }//BUYme //ENTRY SHORT (sell, Bid) void OpenSell() { int gle=0; int ticket=0; double SL=0; double TP=0; int loopcount; // PLACE order is independent of MODIFY order. // This is mandatory for ECNs and acceptable for retail brokers loopcount=0; while(true) { bid=MarketInfo(mySymbol,MODE_BID); ask=MarketInfo(mySymbol,MODE_ASK); ticket=OrderSend(mySymbol,OP_SELL,Lots,bid,Slippage,0,0,TradeComment,MagicNumber,Red); gle=GetLastError(); if(gle==0) { logwrite(TradeComment,"SELL PLACED Ticket="+ticket+" Bid="+bid+" Lots="+Lots); TradeAllowed[ptrPairz]=false; break; } else { logwrite(TradeComment,"-----ERROR----- placing SELL order: Lots="+Lots+" SL="+SL+" TP="+TP+" Bid="+bid+" Ask="+ask+" ticket="+ticket+" Err="+gle+" "+ErrorDescription(gle)); RefreshRates(); Sleep(500); loopcount++; if(loopcount>maxloop) { logwrite(TradeComment,"-----ERROR----- Giving up on placing SELL order"); return(gle); } } }//while // modify the order for users TP & SL loopcount=0; while(true) { bid=MarketInfo(mySymbol,MODE_BID); ask=MarketInfo(mySymbol,MODE_ASK); // don't set TP and SL both to zero, they're already there if(LossLimit==0 && ProfitMade==0) break; if(LossLimit ==0) SL=0; if(ProfitMade ==0) TP=0; if(LossLimit >0) SL=bid+((LossLimit+LL2SL)*myPoint ); if(ProfitMade >0) TP=bid-((ProfitMade+LL2SL)*myPoint ); OrderModify(ticket,OrderOpenPrice(),SL,TP,0,Red); gle=GetLastError(); if(gle==0) { logwrite(TradeComment,"SELL OPENMOD Ticket="+ticket+" Bid="+bid+" Lots="+Lots+" SL="+SL+" TP="+TP); break; } else { logwrite(TradeComment,"-----ERROR----- modifying SELL order: Lots="+Lots+" SL="+SL+" TP="+TP+" Bid="+bid+" Ask="+ask+" ticket="+ticket+" Err="+gle+" "+ErrorDescription(gle)); RefreshRates(); Sleep(500); loopcount++; if(loopcount>maxloop) { logwrite(TradeComment,"-----ERROR----- Giving up on placing SELL order"); return(gle); } } }//while }//SELLme void CloseBuy (string myInfo) { int gle; int cnt; int OrdersPerSymbol; int loopcount=0; string bTK=" Ticket="+OrderTicket(); string bSL=" SL="+OrderStopLoss(); string bTP=" TP="+OrderTakeProfit(); string bPM; string bLL; string bER; bPM=" PM="+ProfitMade; bLL=" LL="+LossLimit; while(true) { bid=MarketInfo(mySymbol,MODE_BID); OrderClose(OrderTicket(),OrderLots(),bid,Slippage,White); gle=GetLastError(); bER=" error="+gle+" "+ErrorDescription(gle); if(gle==0) { logwrite(TradeComment,"CLOSE BUY "+myInfo+ bTK + bSL + bTP + bPM + bLL); break; } else { logwrite(TradeComment,"-----ERROR----- CLOSE BUY "+myInfo+ bER +" Bid="+bid+ bTK + bSL + bTP + bPM + bLL); RefreshRates(); Sleep(500); } loopcount++; if(loopcount>maxloop) { logwrite(TradeComment,"-----ERROR----- Giving up on closing BUY order"); return(gle); } }//while } void CloseSell (string myInfo) { int gle; int cnt; int OrdersPerSymbol; int loopcount=0; string sTK=" Ticket="+OrderTicket(); string sSL=" SL="+OrderStopLoss(); string sTP=" TP="+OrderTakeProfit(); string sPM; string sLL; string sER; sPM=" PM="+ProfitMade; sLL=" LL="+LossLimit; while(true) { ask=MarketInfo(mySymbol,MODE_ASK); OrderClose(OrderTicket(),OrderLots(),ask,Slippage,Red); gle=GetLastError(); sER=" error="+gle+" "+ErrorDescription(gle); if(gle==0) { logwrite(TradeComment,"CLOSE SELL "+myInfo + sTK + sSL + sTP + sPM + sLL); break; } else { logwrite(TradeComment,"-----ERROR----- CLOSE SELL "+myInfo+ sER +" Ask="+ask+ sTK + sSL + sTP + sPM + sLL); RefreshRates(); Sleep(500); } loopcount++; if(loopcount>maxloop) { logwrite(TradeComment,"-----ERROR----- Giving up on closing SELL order"); return(gle); } }//while } // Function to correct the value of Point // for brokers that add an extra digit to price // Courtesy of Robert Hill double SetPoint() { double mPoint; int digits=MarketInfo(mySymbol,MODE_DIGITS); if (digits < 4) { mPoint = 0.01; } else { mPoint = 0.0001; } return(mPoint); }